package com.why.rpc.core.server.beanregistrar;


import com.why.rpc.core.server.annotation.RpcService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.why.rpc.core.common.enums.ErrorEnum;
import com.why.rpc.core.common.exception.RpcException;
import com.why.rpc.core.common.nacos.DefaultNacosServiceRegistry;
import com.why.rpc.core.common.nacos.ServiceRegistry;
import com.why.rpc.core.server.annotation.RpcScan;
import com.why.rpc.core.server.config.WhyRpcConfigPorperties;
import com.why.simpleboot.core.common.utils.SimpleIocUtils;
import com.why.simpleboot.core.common.utils.SimpleReflectUtils;
import com.why.simpleboot.core.configration.SimpleBootConfiguration;
import com.why.simpleboot.core.core.ApplicationContext;
import com.why.simpleboot.core.core.factory.BeanFactory;
import com.why.simpleboot.core.extend.ImportAfterBeanRegistrar;

import java.net.InetSocketAddress;
import java.util.List;
import java.util.Set;

/**
 * @program: why-rpc-framework
 * @description:
 * @author: @why
 * @create: 2021-03-17 13:12
 **/

public class WhyRpcScanRegistrar implements ImportAfterBeanRegistrar {
    private static final Logger log = LoggerFactory.getLogger(WhyRpcScanRegistrar.class);
    private static final String SERVER_RUNNER_PACKAGE = "com.why.rpc.extend";
    private ServiceRegistry registry;
    private SimpleBootConfiguration configuration;

    public WhyRpcScanRegistrar() {
        registry = new DefaultNacosServiceRegistry();
    }

    /**
     * 通过RpcScan所在的路径，扫描所有被RpcService标注的类，注册到Ioc容器里面，然后提交到注册中心
     *
     * @param applicationContext:应用上下文
     * @param scanPackages:导入bean所在的包
     * @param mainClass:启动类
     */
    @Override
    public void registerBeans(ApplicationContext applicationContext, List<String> scanPackages, Class<?> mainClass) {
        int port = WhyRpcConfigPorperties.getPort();
        String host = WhyRpcConfigPorperties.getHost();
        BeanFactory beanFactory = applicationContext.getBeanFactory();
        try {
            log.info("开始获取启动类上面的注解");
            if (!mainClass.isAnnotationPresent(RpcScan.class)) {
                throw new RpcException(ErrorEnum.NO_SERVERSCAN_ANNOTATION_ERROR);
            }
            log.info("开始从RpcScan注解上面获取服务提供者位置");
            String packageBase = mainClass.getAnnotation(RpcScan.class).servicesPackageBase();
            if ("".equals(packageBase)) {
                log.info("未指定服务的位置，开始设置扫描启动类父包下面的所有的包");
                String location = mainClass.getCanonicalName();
                packageBase = location.substring(0, location.lastIndexOf("."));
            }
            log.info("服务类的位置是:{}", packageBase);
            Set<Class<?>> services = SimpleReflectUtils.getClassesByAnnotation(RpcService.class, packageBase);

            log.info("开始去注册服务。。");
//            遍历所有被RpcService标注的类
            for (Class<?> service : services) {
                //看看容器中有无该类，有的话直接上报就行
                Object bean = beanFactory.getBeanByType(service);
                if (bean != null) {
                    String name = SimpleIocUtils.getBeanName(bean.getClass());
                    registry.register(name, new InetSocketAddress(host, port));
//               容器中没有该类，那就实例化并放入容器里面
                } else {
                    //                往容器里面放类
                    Class<?>[] interfaces = service.getInterfaces();
                    if (interfaces.length != 1) {
                        throw new RpcException(ErrorEnum.NO_NAME);
                    } else {
                        String name = interfaces[0].getName();
                        beanFactory.setBean(name, SimpleReflectUtils.getInstance(service));
                        registry.register(name, new InetSocketAddress(host, port));
                    }
                }
            }
//            最后告诉容器要扫描这个路径下的类，这个路径下的类实现了runner接口，完成服务提供者的启动
            scanPackages.add(SERVER_RUNNER_PACKAGE);
        } catch (Exception e) {
            log.error("", e);
        }

    }
}
